package com.taotao.tools.mybatis.plugins.sass.ds;

import com.google.common.base.Preconditions;
import com.taotao.tools.core.str.StringUtil;
import com.taotao.tools.mybatis.plugins.sass.ds.excepiton.SassDataSrouceException;
import com.taotao.tools.mybatis.plugins.sass.ds.utils.DataSourceUtil;
import com.taotao.tools.mybatis.plugins.sass.ds.utils.PropertyUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.jndi.JndiObjectFactoryBean;

import javax.naming.NamingException;
import javax.sql.DataSource;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *
 * </p>
 *
 * @author youbeiwuhuan
 * @version 1.0.0
 * @date 2023/4/26 9:26
 */

@EnableConfigurationProperties({SassDataSourceProperties.class})
@ConditionalOnProperty(prefix = "spring.sass.datasource", name = "enabled", havingValue = "true", matchIfMissing = false)
@RequiredArgsConstructor
public class SassDataSourceConfiguration  implements EnvironmentAware {


    private final SassDataSourceProperties props;
    private final Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();

    private final String jndiName = "jndi-name";








    @Override
    public void setEnvironment(Environment environment) {
        String prefix = "spring.sass.datasource.";
        for (String each : getDataSourceNames(environment, prefix)) {
            try {
                dataSourceMap.put(each, getDataSource(environment, prefix, each));
            } catch (final ReflectiveOperationException ex) {
                throw new SassDataSrouceException("Can't find datasource type!", ex);
            } catch (final NamingException namingEx) {
                throw new SassDataSrouceException("Can't find JNDI datasource!", namingEx);
            }
        }
    }

    private List<String> getDataSourceNames(final Environment environment, final String prefix) {
        StandardEnvironment standardEnv = (StandardEnvironment) environment;
        standardEnv.setIgnoreUnresolvableNestedPlaceholders(true);
        String names = standardEnv.getProperty(prefix + "names");
        if(StringUtil.isBlank(names)){
            throw new IllegalStateException("misss  "+prefix+"names");
        }

        return Arrays.asList(names.split(","));
    }

    @SuppressWarnings("unchecked")
    private DataSource getDataSource(final Environment environment, final String prefix, final String dataSourceName) throws ReflectiveOperationException, NamingException {
        Map<String, Object> dataSourceProps = PropertyUtil.handle(environment, prefix + dataSourceName.trim(), Map.class);
        Preconditions.checkState(!dataSourceProps.isEmpty(), "Wrong datasource properties!");
        if (dataSourceProps.containsKey(jndiName)) {
            return getJndiDataSource(dataSourceProps.get(jndiName).toString());
        }
        DataSource result = DataSourceUtil.getDataSource(dataSourceProps.get("type").toString(), dataSourceProps);
        //TODO  sharding-jdbc这里代码还没看懂
//        DataSourcePropertiesSetterHolder.getDataSourcePropertiesSetterByType(dataSourceProps.get("type").toString()).ifPresent(
//                dataSourcePropertiesSetter -> dataSourcePropertiesSetter.propertiesSet(environment, prefix, dataSourceName, result));
        return result;
    }


    private DataSource getJndiDataSource(final String jndiName) throws NamingException {
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setResourceRef(true);
        bean.setJndiName(jndiName);
        bean.setProxyInterface(DataSource.class);
        bean.afterPropertiesSet();
        return (DataSource) bean.getObject();
    }
}
